/** 
 * \file gdrotm.cu
 * \author Kyle E. Niemeyer
 * \date 10/04/2011
 *
 * Based on "drotm.f" from BLAS.
 *
 */

////////////////////////////////////////////////////////////////////////

/** gdrotm applies a modified Givens rotation.
 *
 * \param[in]     n       number of ordered pairs, dimension of arrays
 * \param[in,out] dx      array of x-coordinates
 * \param[in]     incx    increment between elements of dx
 * \param[in,out] dy      array of y-coordinates
 * \param[in]     incy    increment between elements of dy
 * \param[in]     dparam  rotation matrix information, dimension 5
 */
__device__ __inline__ void gdrotm ( int n, double *dx, int incx, double *dy, int incy, const double *dparam )
{
  
  double dh11, dh12, dh21, dh22;
  
  double dflag = dparam[0];
  
  if ( ( n <= 0 ) || ( (dflag + 2.0) == 0.0 ) ) return;
  
  if ( ( incx == incy ) && ( incx > 0 ) {
    
    uint nsteps = n * incx;
    
    if ( dflag < 0.0 ) {
      
      dh11 = dparam[1];
      dh12 = dparam[3];
      dh21 = dparam[2];
      dh22 = dparam[4];
      
      for ( uint i = 0; i < nsteps; i += incx ) {
        double w = dx[i];
        double z = dy[i];
        dx[i] = w * dh11 + z * dh12;
        dy[i] = w * dh21 + z * dh22;
      }
      
    } else if ( dflag == 0.0 ) {
      
      dh12 = dparam[3];
      dh21 = dparam[2];
      
      for ( uint i = 0; i < nsteps; i += incx ) {
        double w = dx[i];
        double z = dy[i];
        dx[i] = w + z * dh12;
        dy[i] = w * dh21 + z;
      }
      
    } else {
      
      dh11 = dparam[1];
      dh22 = dparam[4];
      
      for ( uint i = 0; i < nsteps; i += incx ) {
        double w = dx[i];
        double z = dy[i];
        dx[i] = w * dh11 + z;
        dy[i] = -w + dh22 * z;
      }
      
    } // end dflag if
    
  } else {
    
    uint kx = 1;
    uint ky = 1;
    if ( incx < 0 ) kx = 1 + (1 - n) * incx;
    if ( incy < 0 ) ky = 1 + (1 - n) * incy;
    
    if ( dflag < 0.0 ) {
      
      dh11 = dparam[1];
      dh12 = dparam[3];
      dh21 = dparam[2];
      dh22 = dparam[4];
      
      for ( uint i = 0; i < n; ++i ) {
        double w = dx[kx];
        double z = dy[ky];
        dx[kx] = w * dh11 + z * dh12;
        dy[ky] = w * dh21 + z * dh22;
        kx += incx;
        dy += inxy;
      }
      
    } else if ( dlfag == 0.0 ) {
      
      dh12 = dparam[3];
      dh21 = dparam[2];
      
      for ( uint i = 0; i < n; ++i ) {
        double w = dx[kx];
        double z = dy[ky];
        dx[kx] = w + z * dh12;
        dy[ky] = w * dh21 + z;
        kx += incx;
        ky += incy;
      }
      
    } else {
      
      dh11 = dparam[1];
      dh22 = dparam[4];
      
      for ( uint i = 0; i < n; ++i ) {
        double w = dx[kx];
        double z = dy[ky];
        dx[kx] = w * dh11 + z;
        dy[ky] = -w + dh22 * z;
        kx += incx;
        ky += incy;
      }
      
    } // end dflag if
    
  } // end incx if
  
} // end gdrotm